﻿using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using Species;
using System.Data.SqlClient;
namespace SpeciesTest
{
    
    
    /// <summary>
    ///This is a test class for SpeciesDALTest and is intended
    ///to contain all SpeciesDALTest Unit Tests
    ///</summary>
    [TestClass()]
    public class SpeciesDALTest
    {

        public const string PRODUCTION_DB_NAME = "SpeciesDatabase";
        public const string TEST_DB_NAME = "SpeciesDatabaseTest";
        public const string CLONE_CONNECTION_STRING =
            @"Data Source=.\SQLEXPRESS;Initial Catalog=master;Integrated Security=True;MultipleActiveResultSets=True";

        private static string databaseDirectory;

        [ClassInitialize]
        public static void InitTestDatabase(TestContext testContext)
        {
            databaseDirectory = testContext.TestDeploymentDir;

            CloneDatabase();

            PopulateTestingData();
        }
  
        private static void PopulateTestingData()
        {
            SpeciesDatabaseEntities context = new SpeciesDatabaseEntities();
            Country country = new Country();

            country.CountryName = "France";
            country.ContinentId = 1;

            context.Countries.AddObject(country);

            country.CountryName = "Germany";
            country.ContinentId = 1;

            context.Countries.AddObject(country);


        }

        private static void CloneDatabase()
        {
            // Clone the production database over the testing database
            string sqlCloneProductionDB = String.Format(@"
				USE master

				BACKUP DATABASE {0} TO DISK='{1}\{0}.bak'

				IF EXISTS(SELECT * FROM sys.sysdatabases where name='{2}')
				BEGIN
					ALTER DATABASE {2} SET SINGLE_USER WITH ROLLBACK IMMEDIATE
					DROP DATABASE {2}
				END

				RESTORE DATABASE {2} FROM DISK='{1}\{0}.bak'
				WITH
				MOVE '{0}' TO '{1}\{2}.mdf',
				MOVE '{0}_log' TO '{1}\{2}_Log.ldf'
			", PRODUCTION_DB_NAME, databaseDirectory, TEST_DB_NAME);

            SqlConnection dbConnection =
                new SqlConnection(CLONE_CONNECTION_STRING);
            dbConnection.Open();
            using (dbConnection)
            {
                SqlCommand cloneDBCmd = new SqlCommand(
                    sqlCloneProductionDB, dbConnection);
                cloneDBCmd.ExecuteNonQuery();
            }
        }

        [ClassCleanup]
        public static void CleanupTestDatabase()
        {
            // Drop the testing database
            SpeciesDatabaseEntities dbContext = new SpeciesDatabaseEntities();
            string sqlDropTestDatabase = String.Format(@"
				USE master

				IF EXISTS(SELECT * FROM sys.sysdatabases where name='{0}')
				BEGIN
					ALTER DATABASE {0} SET SINGLE_USER WITH ROLLBACK IMMEDIATE
					DROP DATABASE {0}
				END
			", TEST_DB_NAME);
            dbContext.ExecuteStoreCommand(sqlDropTestDatabase);
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for AddCountry
        ///</summary>
        [TestMethod()]
        public void AddCountryTest()
        {
            Country newCountry= new Country();
            newCountry.CountryName = "blabla";
            newCountry.ContinentId = 1;
            SpeciesDatabaseEntities context = new SpeciesDatabaseEntities();
            context.Countries.AddObject(newCountry);
            context.SaveChanges();
            SpeciesDatabaseEntities otherContext = new SpeciesDatabaseEntities();
            Country otherCountry =  otherContext.Countries.SingleOrDefault(
                c => c.ContryId == newCountry.ContryId);
            Assert.AreEqual(otherCountry.ContryId, newCountry.ContryId);
            Assert.AreEqual(otherCountry.CountryName.Trim(), newCountry.CountryName);
            Assert.AreEqual(otherCountry.ContinentId, newCountry.ContinentId);
        }

        /// <summary>
        ///A test for DeleteCountry
        ///</summary>
        [TestMethod()]
        public void DeleteCountryTest()
        {
            SpeciesDatabaseEntities context = new SpeciesDatabaseEntities();
            Country newCountry = new Country();
            newCountry.ContinentId = 1;
            newCountry.CountryName = "123";
            newCountry.ContryId = 100;
            context.Countries.AddObject(newCountry);
            SpeciesDatabaseEntities otherContext = new SpeciesDatabaseEntities();
            context.SaveChanges();
            Country countryToDelete = otherContext.Countries.FirstOrDefault(c => c.ContryId == newCountry.ContryId);
            otherContext.Countries.DeleteObject(countryToDelete);
            otherContext.SaveChanges();

            foreach (var country in otherContext.Countries)
            {
                Assert.AreNotEqual(newCountry.ContryId,country.ContryId);
            }
        }

        /// <summary>
        ///A test for DeletePoisonosMushroomsByContinent
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(Exception), "There will more plants than mushrooms")]
        public void DeletePoisonosMushroomsByContinentTest()
        {
            SpeciesDatabaseEntities context = new SpeciesDatabaseEntities();
            SpeciesDAL utils = new SpeciesDAL();
            int continentId = 2;
            int testResult = utils.DeletePoisonosMushroomsByContinent(continentId);
            Assert.AreEqual(0,0);
            
        }

        [TestMethod()]
        [ExpectedException(typeof(Exception), "There will more plants than mushrooms")]
        public void DeletePoisonosMushroomsByContinentExeptionTest()
        {
            SpeciesDatabaseEntities context = new SpeciesDatabaseEntities();
            Species.Species species = new Species.Species();
            species.SpeciesName = "kdjawk";
            species.AverageLifeSpan = 1;
            species.Color = "dawdw";
            species.Size = "dwdaw";
            species.SpeciesTypeId = 2;

            for (int i = 0; i < 10; i++) 
            {
                context.Species.AddObject(species);
            }
            context.SaveChanges();
            SpeciesDAL accessor = new SpeciesDAL();
            int continentId = 2;
            int testResult = accessor.DeletePoisonosMushroomsByContinent(continentId);

        }

        /// <summary>
        ///A test for GroupSpeciesByContinent
        ///</summary>
        [TestMethod()]
        public void GroupSpeciesByContinentTest()
        {
            SpeciesDatabaseEntities context = new SpeciesDatabaseEntities();
            IEnumerable<usp_GroupbyContinent_Result> actual =  context.usp_GroupbyContinent("Europe");
            List<int> expected = new List<int>();
            expected.Add(3);
            expected.Add(1);

            Assert.AreEqual(expected[0], actual.FirstOrDefault().Number_of_species);
            

        }

        /// <summary>
        ///A test for ReadCountry
        ///</summary>
        [TestMethod()]
        public void ReadCountryTest()
        {
            SpeciesDatabaseEntities context = new SpeciesDatabaseEntities();
            Country testCountry = context.Countries.First();

            Country country = new Country();
            country.ContryId = 1;
            country.CountryName = "Bulgaria";
            country.ContinentId = 1;

            Assert.AreEqual(country.ContryId, testCountry.ContryId);
            Assert.AreEqual(country.CountryName, testCountry.CountryName.Trim());
            Assert.AreEqual(country.ContinentId, testCountry.ContinentId);

        }

        /// <summary>
        ///A test for UpdateCountry
        ///</summary>
        [TestMethod()]
        public void UpdateCountryTest()
        {
            SpeciesDatabaseEntities context = new SpeciesDatabaseEntities();
            SpeciesDatabaseEntities otherContext = new SpeciesDatabaseEntities();
            Country testCountry = context.Countries.FirstOrDefault();
            Country otherCountry = otherContext.Countries.FirstOrDefault();
            testCountry.CountryName = "pesho";
            context.SaveChanges();

            Assert.AreNotEqual(otherCountry.CountryName, testCountry.CountryName);
        }
    }
}
